
#include "../include/Dlt645ParseTask.h"
#include "../include/dlt645def.h"
#include "CLogger.h"
#include "../../common/include/common.h"
#include "../../db/include/CDBManager.h"
#include "../../common/include/LinkageManager.h"

#include <string.h>
#include <sstream>

//#define  DLT645_LINKAGE_TOPIC      "pemd/rule/linkage/pemd/v1/default"
#define  DATAFIELD_MAXLEN           25600    //单帧数据域最长200  *128

CDlt645ParseTask::CDlt645ParseTask(std::shared_ptr<CConfigManager> confMana, std::shared_ptr<CMosquittoManager> mosqMana,
                                TASK_PARAMS *pdev_task,std::list<std::shared_ptr<ST_DL645_RSPDATA>> &RspData)
{
    m_confMana = confMana;
    m_mosqMana = mosqMana;
    m_rspData.swap(RspData);
    if(NULL == pdev_task){
        m_pdev_task = NULL;
    } else {
        m_pdev_task = new TASK_PARAMS();
        *m_pdev_task = *pdev_task;
    }
    m_ioffset = 0;
}

CDlt645ParseTask::~CDlt645ParseTask()
{
    if(NULL != m_pdev_task){
        delete m_pdev_task;
    }
}

void CDlt645ParseTask::run()
{
    int64_t dev_id = 0;
    int len = 0,blklen=0,startpos=0;
    uint8_t ctrlcode = ENUM_CTRLCODE_RSP_NONE;

    uint8_t* pdataField = new uint8_t[DATAFIELD_MAXLEN];
    if (nullptr == pdataField)
    {
        CLogger::getInstance()->LOG_E("CDlt645ParseTask::run new memeory error.");
        return;
    }
    memset(pdataField, 0, DATAFIELD_MAXLEN);
    m_points_value.clear();

    while (!m_rspData.empty())
    {
        auto rspdata = m_rspData.front();

        dev_id = rspdata->dev_id;
        int64_t rule_id = rspdata->protocol_id;
        std::string cur_di = rspdata->di;

        ctrlcode = get_ctrlcode(rspdata->pdata, rspdata->datalen);
        if (ENUM_CTRLCODE_READ_METERDATA_HAVESUBSEQ_RSP == ctrlcode)  //有后续数据
        {
            m_ioffset = 0;    
            memset(pdataField, 0, DATAFIELD_MAXLEN);
            len = blockdata_recombine(pdataField,rspdata->dev_id, rspdata->di, rspdata->pdata, rspdata->datalen, blklen);

            //块解析
            parse_readingdata_rsp(dev_id, rule_id, cur_di, pdataField, len);
            continue;
        }

        if (ENUM_CTRLCODE_READ_METERDATA_RSP == ctrlcode)
        {
            OutputData("parse frame data",rspdata->pdata, rspdata->datalen);
            //单个数据域解析
            int data_len = get_frmdata_len(rspdata->pdata, rspdata->datalen, startpos);
            if (data_len > 0)
            {
                memcpy(pdataField, rspdata->pdata + startpos, data_len);
                parse_readingdata_rsp(dev_id, rule_id, cur_di, pdataField, data_len);
            }           
        }
        else if ((ENUM_CTRLCODE_READ_METERDATA_ABNORMAL == ctrlcode) || (ENUM_CTRLCODE_READ_SUBSEQDATA_ABNORMAL == ctrlcode))
        {
            parse_readingdata_abnormal(ctrlcode, rspdata->pdata, rspdata->datalen);
        }
        else if (ENUM_CTRLCODE_RSP_NONE == ctrlcode)
        {
            CLogger::getInstance()->LOG_E("CDlt645ParseTask::run--frame format error.");
        }
        else{
            CLogger::getInstance()->LOG_W("CDlt645ParseTask::run--frame ctrlcode(0x%02X) not surport.",ctrlcode);
        }    

        if (rspdata->pdata)
        {
            delete[] rspdata->pdata;
            rspdata->pdata = NULL;
        }
        m_rspData.pop_front();
    }

    //数据上报--按dev_id
    if (m_points_value.size() >0)
    {
        if ((NULL != m_pdev_task) && (m_pdev_task->type == TASK_TYPE_GET_CMD_RULE))
        {
            CReportManager::getInstance().report_get_cmd_data(m_pdev_task, "CMD_GET_COMMAND_RULE", m_mosqMana, m_points_value);
        }
        else{
            CReportManager::getInstance().push_data(dev_id, m_points_value);
        }     
    }
    else{
        CLogger::getInstance()->log_i("CDlt645ParseTask run no parsedata.");
    }

    if (pdataField)
    {
        delete[] pdataField;
    }
}

int  CDlt645ParseTask::blockdata_recombine(uint8_t* pdataField, int64_t devid, const std::string& di, uint8_t* pdata, int len, int & blklen)
{
    int pre_seq_id = 0;  
    int startpos = 0;
    m_ioffset = 0;
    
    int data_len = get_frmdata_len(pdata, len, startpos);
    int  total_len = data_len;
    if (data_len >0)
    {
        memcpy(pdataField + m_ioffset, pdata + startpos, data_len);
        m_ioffset += data_len;
    }
    if (pdata)
    {
        delete[] pdata;
    }
    m_rspData.pop_front();


    CLogger::getInstance()->log_d("blockdata_recombine:devid=%lld,di=%s. list size=%d",devid,di.c_str(),m_rspData.size());

    //先拼接有后续数据的帧--控制码0xB2
    auto it_rspdata = m_rspData.begin();
    while ( it_rspdata != m_rspData.end())
    {
        auto rspdata = *it_rspdata;
        uint8_t code = get_ctrlcode(rspdata->pdata, rspdata->datalen);
        if ((rspdata->dev_id == devid) && (rspdata->di.compare(di) ==0) && (ENUM_CTRLCODE_READ_SUBSEQDATA_HAVESUBSEQ_RSP ==code))
        {
            //帧序号判断，拼接数据
            int seq_id = get_seqid(rspdata->pdata, rspdata->datalen);
            if (seq_id == pre_seq_id +1)   //帧序号为上一帧+1
            {
                data_len = get_frmdata_len(rspdata->pdata, rspdata->datalen, startpos);
                if (data_len >0)
                {
                    memcpy(pdataField + m_ioffset, rspdata->pdata + startpos, data_len);
                    m_ioffset += data_len;
                    total_len += data_len;
                }                
                pre_seq_id = seq_id;

                if (rspdata->pdata)
                {
                    delete[] rspdata->pdata;
                    rspdata->pdata = NULL;
                }
                it_rspdata = m_rspData.erase(it_rspdata);
                continue;
            }
        }
        it_rspdata++;
    }

    //再拼接无后续数据的帧--控制码0x92
    it_rspdata = m_rspData.begin();
    while (it_rspdata != m_rspData.end())
    {
        auto rspdata = *it_rspdata;
        uint8_t code = get_ctrlcode(rspdata->pdata, rspdata->datalen);
        if ((rspdata->dev_id == devid) && (rspdata->di.compare(di) == 0) && (ENUM_CTRLCODE_READ_SUBSEQDATA_RSP == code))
        {
            //帧序号判断，拼接数据
            int seq_id = get_seqid(rspdata->pdata, rspdata->datalen);
            if (seq_id == pre_seq_id + 1)   //帧序号为上一帧+1
            {
                data_len = get_frmdata_len(rspdata->pdata, rspdata->datalen, startpos);
                if (data_len >0)
                {
                    memcpy(pdataField + m_ioffset, rspdata->pdata + startpos, data_len);
                    m_ioffset += data_len;
                    total_len += data_len;
                }                
                pre_seq_id = seq_id;

                if (rspdata->pdata)
                {
                    delete[] rspdata->pdata;
                    rspdata->pdata = NULL;
                }
                m_rspData.erase(it_rspdata);
                break;   //无后续数据，跳出循环
            }
        }
        it_rspdata++;
    }
    blklen = total_len;

    OutputData("blockdata_recombine all data:", pdataField, total_len);

    return total_len;
}

int  CDlt645ParseTask::parse_readingdata_rsp(int64_t  devid, int64_t rule_id,const std::string& di, uint8_t* pdata, int len)
{
    auto rulesPtr = m_confMana->get_dlt645_rule_points(); //<ruleid,<pointid,pointid>>
    if (nullptr == rulesPtr)
    {
        CLogger::getInstance()->LOG_W("parse_readingdata_rsp: No rule points.");
        return -1;
    }
    auto rule = rulesPtr->find(rule_id);  //<pointid,pointid>
    if (rule == rulesPtr->end())
    {
        CLogger::getInstance()->LOG_W("parse_readingdata_rsp: Not find rule point(id=%lld).",rule_id);
        return -1;
    }

    OutputData("parse_readingdata_rsp data",pdata,len);
     
    std::string strval;
    int blk_id = 0;     //块号
    int offset = 0;
    int blk_num = 0;

    //遍历查询总块数
    for (auto pointid = rule->second.begin(); pointid != rule->second.end(); pointid++)
    {
        auto dlt645pt = m_confMana->get_dlt645_point(pointid->first);
        if (nullptr ==dlt645pt)
        {
            CLogger::getInstance()->LOG_W("parse_readingdata_rsp: get dlt645point error.");
            return -1;
        }
        if (dlt645pt->block_no == blk_num)
        {
            blk_num++;
        }
    }
    int* pblk_len = new int[blk_num + 1];
    if (nullptr ==pblk_len){
        CLogger::getInstance()->LOG_W("parse_readingdata_rsp: new int error.");
        return -1;
    }

    while (offset < len)
    {
        bool bfind = false;
        for (auto pointid = rule->second.begin(); pointid != rule->second.end(); pointid++)
        {
            auto dlt645pt = m_confMana->get_dlt645_point(pointid->first);
            if (dlt645pt->pos + dlt645pt->data_size > dlt645pt->block_size) //超出本块的长度
            {
                CLogger::getInstance()->LOG_W("parse_readingdata_rsp: para error point id=%lld", dlt645pt->id);
                return -1;
            }
            if ((dlt645pt->block_no == blk_id) && (dlt645pt->di.compare(di) == 0))
            {
                bfind = true;
                pblk_len[blk_id] = dlt645pt->block_size;

                int data_size = dlt645pt->data_size;
                if (0 == data_size)
                {
                    CLogger::getInstance()->LOG_W("parse_readingdata_rsp: datasize is 0.");
                    return -1;
                }
                //按编码格式分类
                if (dlt645pt->encode == ENUM_645_ENCODE_BCD)    //BCD码
                { 
                    if (dlt645pt->data_type == ENUM_645_DATATYPE_DATETIME)
                    {
                        strval = get_point_val(pdata + offset + dlt645pt->pos, data_size);
                        strval = get_datatime_val(pdata + offset, data_size, dlt645pt->datetime_format); 
                    }
                    else if (dlt645pt->data_type == ENUM_645_DATATYPE_STRING)
                    {
                        strval = get_point_val(pdata + offset + dlt645pt->pos, data_size);
                    }
                    else{
                        strval = get_point_val(pdata + offset + dlt645pt->pos, data_size);
                        strval = get_final_val(dlt645pt, strval);
                        if (dlt645pt->isAlarm == ENUM_645_ISALARM)
                        {
                            //报警处理
                            parse_dealwith_alert(dlt645pt, devid, strval);
                        }
                    }
                    save_point_value(dlt645pt->id, dlt645pt->data_type, strval);                    
                }
                else if (dlt645pt->encode == ENUM_645_ENCODE_HEX)  //十六进制---不处理字符串和日期型
                {
                    switch (dlt645pt->data_type)
                    {
                    case ENUM_645_DATATYPE_CHAR:
                        strval = get_final_val_ex<char>(dlt645pt, get_decimal_value<char>(dlt645pt, pdata + offset + dlt645pt->pos));
                        break;
                    case ENUM_645_DATATYPE_UNSIGNED_CHAR:
                        strval = get_final_val_ex<unsigned char>(dlt645pt, get_decimal_value<unsigned char>(dlt645pt, pdata + offset + dlt645pt->pos));
                        break;
                    case ENUM_645_DATATYPE_SHORT:
                        strval = get_final_val_ex<short>(dlt645pt, get_decimal_value<short>(dlt645pt, pdata + offset + dlt645pt->pos));
                        break;
                    case ENUM_645_DATATYPE_UNSIGNED_SHORT:
                        strval = get_final_val_ex<unsigned short>(dlt645pt, get_decimal_value<unsigned short>(dlt645pt, pdata + offset + dlt645pt->pos));
                        break;
                    case ENUM_645_DATATYPE_INT:
                        strval = get_final_val_ex<int>(dlt645pt, get_decimal_value<int>(dlt645pt, pdata + offset + dlt645pt->pos));
                        break;
                    case ENUM_645_DATATYPE_UNSIGNED_INT:
                        strval = get_final_val_ex<unsigned int>(dlt645pt, get_decimal_value<unsigned int>(dlt645pt, pdata + offset + dlt645pt->pos));
                        break;
                    case ENUM_645_DATATYPE_FLOAT:
                        strval = get_final_val_ex<float>(dlt645pt, get_decimal_value<float>(dlt645pt, pdata + offset + dlt645pt->pos));
                        break;
                    case ENUM_645_DATATYPE_DOUBLE:
                        strval = get_final_val_ex<double>(dlt645pt, get_decimal_value<double>(dlt645pt, pdata + offset + dlt645pt->pos));
                        break;
                    case ENUM_645_DATATYPE_DATETIME:
                        strval = get_datatime_val(pdata + offset, data_size, dlt645pt->datetime_format);
                        break;
                    case ENUM_645_DATATYPE_STRING:
                        strval = get_hex_str(dlt645pt, pdata + offset + dlt645pt->pos);
                        break;
                    default:
                        break;
                    }
                    save_point_value(dlt645pt->id, dlt645pt->data_type, strval);
                    if (dlt645pt->isAlarm == ENUM_645_ISALARM)
                    {
                        if ((dlt645pt->data_type != ENUM_645_DATATYPE_STRING) && (dlt645pt->data_type != ENUM_645_DATATYPE_DATETIME))
                        {
                            //报警处理
                            parse_dealwith_alert(dlt645pt, devid, strval);
                        }
                    }
                }
                else{
                    CLogger::getInstance()->LOG_W("parse_readingdata_rsp dataencode error,not recognition.");
                    continue;
                }
                //联动处理
                dealwith_linkage(dlt645pt, devid, strval);                               
            }
        }
        if (bfind)
        {
            offset += pblk_len[blk_id];   //块偏移量
            blk_id++;    //循环外块序号计数再增加，可以解析同一个块内偏移量不同的数据项
        }
        //for 循环中没有一个匹配的di，跳出
        else
        {
            if (offset >0) {
                CLogger::getInstance()->LOG_W("parse_readingdata_rsp: data field length > prase length, di=%s.", di.c_str());
            }
            else{
                CLogger::getInstance()->LOG_W("parse_readingdata_rsp: data error,can't matching di=%s.", di.c_str());
            }
            break;
        }
    }
    delete []pblk_len;

    return 0;
}

std::string CDlt645ParseTask::get_hex_str(std::shared_ptr<DLT645_POINT> pt, uint8_t* pdata)
{
    std::string  val = "";
    if ((nullptr == pdata) || (nullptr ==pt)){
        return val;
    }

    OutputData("get_hex_str", pdata, pt->data_size);

    uint8_t byteval = 0;
    char buf[8] = { 0 };
    for (int i = pt->data_size - 1; i >= 0; i--)
    {
        byteval = pdata[i] - FLAG_ERRIDENT;
        sprintf(buf, "%02x", byteval);
        val += buf;
    }
    return val;
}

std::string CDlt645ParseTask::get_point_val(uint8_t* pdata, int bytenum)
{
    std::string  val ="";
    if ((nullptr == pdata) || (0 >=bytenum)){
        return val;
    }
    
    OutputData("get_point_val data",pdata,bytenum);
    
    uint8_t byteval = 0;
    int l = bytenum*2+1;
    char buf[l] = {0};
    for (int i = bytenum - 1; i >= 0; i--)
    {
        byteval = pdata[i] - FLAG_ERRIDENT;
        sprintf(buf, "%02X", byteval);
        val += buf;
    }
    return val;
}
std::string CDlt645ParseTask::get_point_val2(uint8_t* pdata, int bytenum)
{
    std::string  val ="";
    if ((nullptr == pdata) || (0 >=bytenum)){
        return val;
    }
    
    OutputData("get_point_val data",pdata,bytenum);

    uint8_t byteval = 0;
    int l = bytenum*2+1;
    char buf[l] = {0};
    for (int i =0; i < bytenum; i++)
    {
        byteval = pdata[i] - FLAG_ERRIDENT;
        sprintf(buf, "%02X", byteval);
        val += buf;
    }

    return val;
}
std::string CDlt645ParseTask::get_final_val(std::shared_ptr<DLT645_POINT> pt, const std::string& val)
{
    if ((nullptr == pt) || val.empty())
    {
        return "";
    }

    char ret_buf[64] = { 0 };
    char str_format[32] = { 0 };
    double fVal = 0.0f;
    std::string  formula = pt->formula;

    CLogger::getInstance()->log_d("get_final_val:val=%s,formula=%s,scale=%f,decimal=%d",val.c_str(),formula.c_str(),pt->scale,pt->decimal);

    trimstring(formula);
    if (formula.empty())
    {
        try{
            fVal = std::stod(val);
        }catch(...){
            fVal = std::stod("0x"+val);
        }
        fVal *= pt->scale;
    }
    else{
        std::string formula = "echo \"" + pt->formula + "\"|bc";
        formula = string_replace(formula, "X", val);
        if (0 == exec_cmd((char *)formula.c_str(), ret_buf, sizeof(ret_buf))){
            fVal = atof(ret_buf);
        }
    }

    if (0 < pt->decimal){
        snprintf(str_format, sizeof(str_format), "%%.%dlf", pt->decimal);
        snprintf(ret_buf, sizeof(ret_buf), str_format, fVal);
    }
    else {
        snprintf(ret_buf, sizeof(ret_buf), "%.0f", fVal);
    }
    std::string fina_val(ret_buf);

    CLogger::getInstance()->log_d("get_final_val:fval=%f,fmt=%s,retbuf=%s",fVal,str_format,ret_buf);
  

    return fina_val;
}

std::string  CDlt645ParseTask::get_datatime_val(uint8_t* pdata, int bytenum,const std::string& strfmt)
{
    std::string  strval = strfmt;
    char fmtdata[16] = {0};
    char rpstr[12][8] = { "yyyy", "YYYY", "YY","yy", "MM", "DD", "dd", "WW", "HH", "hh", "mm", "ss" };
    char substr[8] = {0};
    int num = 0, idx = -1;
    
    for (int i = 0; i < 12;i++) {
        strncpy(substr, rpstr[i], 8);
        std::string::size_type pos = strval.find(substr);
        if (pos != std::string::npos){
            if (num < bytenum){
                sprintf(fmtdata, "%02X", pdata[bytenum - num -1] - FLAG_ERRIDENT); //数据域中的数据为倒序
            }
            else{
                strncpy(fmtdata, "00", sizeof(fmtdata));
            }
            idx = (int)pos;
            strval.replace(idx, strlen(substr), fmtdata);
            num++;
        }
    }

    return strval;
}
//
int CDlt645ParseTask::save_point_value(int64_t point_id, int data_type, const std::string& value){
    
    auto v_point = m_confMana->get_dlt645_point(point_id);
    if(v_point == nullptr){
        CLogger::getInstance()->LOG_W("CDlt645ParseTask::save_point_value--点数据不存在");
        return -1;
    }
    auto pv = m_points_value.find(v_point->name);
    RESPONSE_DATA data;
    data.point_id = point_id;
    data.data_type = data_type;
    data.value = value;
    data.name = v_point->name;
    data.code = 0;
    data.msg = "success";
    if (pv == m_points_value.end()){
        m_points_value.insert(std::make_pair(data.name, data));
    }
    else{
        m_points_value[data.name] = data;
    }

    {
        CLogger::getInstance()->log_d("save_point_value:id=%lld,datatype=%d,val=%s",point_id,data_type,value.c_str());
    }

    return 0;
}

int CDlt645ParseTask::parse_dealwith_alert(std::shared_ptr<DLT645_POINT> pt, int64_t dev_id, const std::string& value)
{
    if (nullptr == pt)
    {
        return -1;
    }

    double fval = std::stod(value);

    {
        CLogger::getInstance()->log_d("parse_dealwith_alert:val=%f,lower_limit=%f,upper_limit=%f.",fval,pt->lower_limit,pt->upper_limit);
    }

    if ((fval < pt->lower_limit) || (fval > pt->upper_limit))
    {
        std::string str_alertdesc;
        if (fval < pt->lower_limit){
            str_alertdesc = pt->lower_desc;
        }
        else{
            str_alertdesc = pt->upper_desc;
        }
        auto alert_dev = m_confMana->get_dev_alerts()->find(dev_id);
        if (alert_dev == m_confMana->get_dev_alerts()->end()) //此设备、此point无报警信息
        {
            ALERT_DATA  alert_data;
            get_alert_data(dev_id, pt->id, value, alert_data);
            alert_data.alert_desc = str_alertdesc;

            std::unordered_map<int64_t, ALERT_DATA> alerts;
            alerts.insert(std::make_pair(pt->id, alert_data));
            m_confMana->get_dev_alerts()->insert(std::make_pair(dev_id, alerts));
        }
        else
        {
            auto point_alert = alert_dev->second.find(pt->id);
            if (point_alert == alert_dev->second.end()){ //此point无报警信息
                ALERT_DATA  alert_data;
                get_alert_data(dev_id,pt->id,value,alert_data);
                alert_data.alert_desc = str_alertdesc;

                alert_dev->second.insert(std::make_pair(pt->id, alert_data));
            }
            else{
                auto edge_dev = m_confMana->get_edge_device();
                if (nullptr == edge_dev){
                    CLogger::getInstance()->log_d("parse_dealwith_alert:no edge device.");
                    return -1;
                }
                //此前有报警信息，若报警次数阈值不到，阈值+1，更新报警时间和采集值
                //若报警次数阈值达到，报警，置状态位
                point_alert->second.report_time = get_timestamp();
                point_alert->second.value = value;
                point_alert->second.alert_desc = str_alertdesc;
                if (point_alert->second.alert_count +1 < pt->threshold_count){
                    point_alert->second.alert_count++;                    
                    CDBManager::getInstance()->replace_alert_data(point_alert->second);
                }
                else{
                    point_alert->second.state = 1;
                    point_alert->second.value = value;
                    CReportManager::getInstance().report_alert(point_alert->second);
                    CDBManager::getInstance()->replace_alert_data(point_alert->second);
                    alert_dev->second.erase(pt->id);

                    CLogger::getInstance()->log_d("Alert aleady pushed");
                }
            }
        }
    }
    else{
        //数据正常后报警计数-1，直至报警计数为0--报警恢复
        auto dev_alerts = m_confMana->get_dev_alerts()->find(dev_id);
        if (dev_alerts != m_confMana->get_dev_alerts()->end()){
            auto point_alert = dev_alerts->second.find(pt->id);
            if (point_alert != dev_alerts->second.end()){
                if (0 < point_alert->second.alert_count){
                    point_alert->second.alert_count--;
                }
                else{
                    point_alert->second.restore_time = get_timestamp();
                    point_alert->second.state = 2;
                    //保存报警数据
                    CDBManager::getInstance()->replace_alert_data(point_alert->second);
                    dev_alerts->second.erase(pt->id);
                }
            }
            if (1 > dev_alerts->second.size()){
                m_confMana->get_dev_alerts()->erase(dev_id);  //设备ID --dev-id下无报警点
            }
        }
    }

    return 0;
}

int CDlt645ParseTask::dealwith_linkage(std::shared_ptr<DLT645_POINT> pt, int64_t dev_id, const std::string& value)
{
    if ((nullptr == pt) || (0>= dev_id)){
        return -1;
    }

    return LinkageManager::getInstance().parse_linkage(m_confMana, m_mosqMana, dev_id, pt->id, value);
}

void CDlt645ParseTask::parse_readingdata_abnormal(uint8_t ucCode, uint8_t* pData, int iLen)
{
    if ((ENUM_CTRLCODE_READ_METERDATA_ABNORMAL == ucCode) || ((ENUM_CTRLCODE_READ_SUBSEQDATA_ABNORMAL == ucCode)))
    {
        uint8_t errcode = pData[iLen - 3];
        CLogger::getInstance()->LOG_W("The slave station abnormal response:%d", errcode);
    }
    else{
        CLogger::getInstance()->log_w("unidentification ctrl code:%d", ucCode);
    }
    
}

void CDlt645ParseTask::get_alert_data(int64_t dev_id, int64_t point_id, const std::string& value, ALERT_DATA& alert_data)
{
    alert_data.dev_id = dev_id;
    alert_data.alert_count = 1;
    alert_data.point_id = point_id;
    alert_data.report_time = get_timestamp();
    alert_data.state = 0;
    alert_data.restore_time = 0;
    alert_data.value = value;
    alert_data.id = CDBManager::getInstance()->insert_alert_data(alert_data);
}

int CDlt645ParseTask::is_linkage(const std::string& op,const std::string& value1, const std::string& value2){

    CLogger::getInstance()->log_d("is_linkage:op=%s,val=%s,cond_val=%s",op.c_str(),value1.c_str(),value2.c_str());
    
    if (0 == op.compare(">")){
        if (0 < value1.compare(value2)){
            return 1;
        }
    }
    else if (0 == op.compare(">=")){
        if (0 <= value1.compare(value2)){
            return 1;
        }
    }
    else if (0 == op.compare("<")){
        if (0 > value1.compare(value2)){
            return 1;
        }
    }
    else if (0 == op.compare("<=")){
        if (0 >= value1.compare(value2)){
            return 1;
        }
    }
    else if (0 == op.compare("!=")){
        if (0 != value1.compare(value2)){
            return 1;
        }
    }

    return 0;
}

//获取控制吗，若帧错误返回0
uint8_t CDlt645ParseTask::get_ctrlcode(uint8_t* pdata,int len)
{
    uint8_t ctrlcode = 0;
    int prefix_num = verify_dlt645_frame(pdata, len);

    if (prefix_num <0)
    {
        CLogger::getInstance()->LOG_D("get_ctrlcode: frame error.");
        return ctrlcode;
    }
    
    ctrlcode = pdata[prefix_num + 8];

    return ctrlcode;
}

//获取数据域中，数据的长
int CDlt645ParseTask::get_frmdata_len(uint8_t* pdata, int len, int& startpos)
{
    startpos = 0;
    int prefix_num = verify_dlt645_frame(pdata, len);
    if (prefix_num <0)
    {    
        return 0;
    }

    int data_len = 0;
    uint8_t ctrlcode = get_ctrlcode(pdata, len);
    if ((ENUM_CTRLCODE_READ_METERDATA_HAVESUBSEQ_RSP == ctrlcode) || (ENUM_CTRLCODE_READ_METERDATA_RSP == ctrlcode)) {
        data_len = pdata[prefix_num + 9] - 4;  //减去数据标识长   
        startpos = prefix_num + 14;
    }
    else if ((ENUM_CTRLCODE_READ_SUBSEQDATA_RSP == ctrlcode) || (ENUM_CTRLCODE_READ_SUBSEQDATA_HAVESUBSEQ_RSP == ctrlcode)) {
        data_len = pdata[prefix_num + 9] - 5;  //减去数据标识和帧序号长
        startpos = prefix_num + 14;
    }

    CLogger::getInstance()->log_d("get_frmdata_len: len=%d", data_len);

    return data_len;
}

//获取帧序号，无帧序号返回-1  
int CDlt645ParseTask::get_seqid(uint8_t* pdata, int len)
{
    int seqid = -1;
    if (verify_dlt645_frame(pdata,len) <0)
    {
        return seqid;
    }

    seqid = pdata[len - 3] -FLAG_ERRIDENT;

    return seqid;
}

//dlt645帧校验，正确是返回前导符个数，错误返回 <0
int  CDlt645ParseTask::verify_dlt645_frame(uint8_t* pdata, int len)
{
    int prefix_num = 0;
    if ((MIN_FRAME_LEN > len) || (!pdata))
    {
        return -1;
    }
    
    for (int i = 0; i < 4; i++) {
        if (CHR_PREFIX == pdata[i])
        {
            prefix_num++;
        }
    }
    if ((CHR_FRMSTART != pdata[prefix_num]) || (CHR_FRMSTART != pdata[prefix_num + 7]))
    {
        return -2;
    }

    uint8_t cscode = CalcCSVal(pdata+prefix_num, len - 2 -prefix_num);
    if (cscode != pdata[len -2])
    {
        return -4;
    }

    if (pdata[len - 1] != CHR_FRMEND)
    {
        return -3;
    }

    return prefix_num;
}

template<typename T>
T CDlt645ParseTask::get_decimal_value(std::shared_ptr<DLT645_POINT> pt, uint8_t* pdata)
{
    if (nullptr == pdata){
        return 0;
    }
    uint8_t bytedata[16] = { 0 };
    int bytenum = 0;
    switch (pt->data_type)
    { 
    case ENUM_645_DATATYPE_SHORT:
    case ENUM_645_DATATYPE_UNSIGNED_SHORT:
        bytenum = 2;
        break;
    case ENUM_645_DATATYPE_INT:
    case ENUM_645_DATATYPE_UNSIGNED_INT:
    case ENUM_645_DATATYPE_FLOAT:
        bytenum = 4;
        break;
    case ENUM_645_DATATYPE_INT64:
    case ENUM_645_DATATYPE_UNSIGNED_INT64:
    case ENUM_645_DATATYPE_DOUBLE:
        bytenum = 8;
        break;
    default:
    case ENUM_645_DATATYPE_CHAR:
    case ENUM_645_DATATYPE_UNSIGNED_CHAR:
        bytenum = 1;
        break;
    }

    if (pt->byte_Order == ENUM_645HEX_ORDER_LITTLE_ENDIAN){
        for (int i= 0; i < bytenum;i++)
        {
            bytedata[i] = pdata[i] - FLAG_ERRIDENT;
        }
    }
    else if (pt->byte_Order == ENUM_546HEX_ORDER_BIG_ENDIAN) {
        for (int i = 0; i < bytenum; i++)
        {
            bytedata[i] = pdata[bytenum - 1 - i] - FLAG_ERRIDENT;
        }
    }
    CLogger::getInstance()->log_d("get_decimal_value:rule_id=%lld,di=%s", pt->protocol_id, pt->di.c_str());
    OutputData("get_decimal_value", bytedata, bytenum);

    T value;
    if (pt->data_type == ENUM_645_DATATYPE_FLOAT)
    {
        float fval = 0;
        memcpy(&fval, bytedata, bytenum);
        value = fval;
    }
    else if (pt->data_type == ENUM_645_DATATYPE_DOUBLE)
    {
        double dfval = 0;
        memcpy(&dfval, bytedata, bytenum);
        value = dfval;
    }
    else{
	    value =0;
        for (int j = 0; j < bytenum;j++)
        {
            value += (bytedata[j] * (int)pow(256, j));
        }
    }

    return value;
}

template<typename T>
std::string CDlt645ParseTask::get_final_val_ex(std::shared_ptr<DLT645_POINT> point, T value){
    if (nullptr == point){
        return "";
    }
    double v = 0.0f;
    char ret_buf[64] = { 0 };
    char str_format[32] = { 0 };
    if (point->formula.empty()){
        v = value * point->scale;
    }
    else {
        std::string formula = "echo \"" + point->formula + "\"|bc";
        std::stringstream fstr;
        fstr << value;

        formula = string_replace(formula, "X", fstr.str());
        if (0 == exec_cmd((char *)formula.c_str(), ret_buf, sizeof(ret_buf))){
            v = atof(ret_buf);
        }
    }
    if (0 < point->decimal){
        snprintf(str_format, sizeof(str_format), "%%.%dlf", point->decimal);
        snprintf(ret_buf, sizeof(ret_buf), str_format, v);
    }
    else {
        snprintf(ret_buf, sizeof(ret_buf), "%lf", v);
    }

    return ret_buf;
}


//校验码计算
uint8_t CDlt645ParseTask::CalcCSVal(uint8_t* pData, int iLen)
{
    unsigned char CS = 0;
    unsigned int uiVal = 0;
    int i = 0;

    for (i = 0; i < iLen; i++)
    {
        uiVal += pData[i];
    }

    CS = uiVal % 256;

    return CS;
}
//空格字符串，清空
void CDlt645ParseTask::trimstring(std::string & str)
{
    size_t s = str.find_first_not_of(" ");
    size_t e = str.find_last_not_of(" ");
    if ((s == std::string::npos) && (e == std::string::npos)){
        str.clear();
    }
}

void CDlt645ParseTask::OutputData(const char* pName,  uint8_t* pData, int len)
{
    char  szInfo[512] = { 0 };
    char  szch[8] = { 0 };
    int info_len = len;
    if(info_len > 170){
        info_len =170;
    }
    for (int i = 0; i < info_len; i++){
        sprintf(szch, "%02X ", pData[i]);
        strcat(szInfo, szch);
    }
    
    CLogger::getInstance()->log_d("%s:%s", pName,szInfo);
}

